package com.nbcio.iot.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.nbcio.iot.config.IotModbusPollingProperties;
import com.nbcio.iot.domain.entity.IotDevice;
import com.nbcio.iot.mapper.IotDeviceMapper;
import com.nbcio.iot.protocol.modbus.ModbusManager;
import com.nbcio.iot.protocol.mqtt.MqttClientManager;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import com.nbcio.iot.service.IotDataCollectionService;

@Slf4j
@Service
@RequiredArgsConstructor
public class ModbusPollingService {

    private final IotModbusPollingProperties pollingProperties;
    private final IotDeviceMapper deviceMapper;
    private final com.nbcio.iot.mapper.IotProductMapper productMapper;
    private final ModbusManager modbusManager;
    private final MqttClientManager mqttClientManager;
    private final IotDataCollectionService dataCollectionService;

    private final ObjectMapper objectMapper = new ObjectMapper();

    /** 记录每个设备点位的下次运行时间，用于 periodSec 节流 */
    private final Map<String, Long> nextRunAtMsByKey = new ConcurrentHashMap<>();

    @Scheduled(fixedDelayString = "${iot.modbus.polling.fixedDelayMs:5000}")
    public void poll() {
        if (!pollingProperties.isEnabled()) {
            return;
        }
        long now = System.currentTimeMillis();
        try {
            // 不再直接轮询，而是由 IotDataCollectionService 处理
            log.debug("[MODBUS-POLLING] 数据采集已改为消息队列驱动");
        } catch (Exception e) {
            log.warn("[MODBUS] polling error: {}", e.getMessage());
        }
    }

    private Map<String, Object> resolveMergedConfig(IotDevice device) {
        try {
            Map<String, Object> productCfg = null;
            if (device.getProductId() != null) {
                com.nbcio.iot.domain.entity.IotProduct product = productMapper.selectById(device.getProductId());
                if (product != null && product.getProtocolConfig() != null) {
                    productCfg = objectMapper.readValue(product.getProtocolConfig(), Map.class);
                }
            }
            Map<String, Object> deviceOverride = null;
            if (device.getProtocolConfigOverride() != null && !device.getProtocolConfigOverride().isEmpty()) {
                deviceOverride = objectMapper.readValue(device.getProtocolConfigOverride(), Map.class);
            }
            Map<String, Object> merged = new HashMap<>();
            if (productCfg != null) merged.putAll(productCfg);
            if (deviceOverride != null) merged.putAll(deviceOverride);
            return merged;
        } catch (Exception e) {
            log.warn("[MODBUS] config parse error deviceId={}, err={}", device.getDeviceId(), e.getMessage());
            return null;
        }
    }

    private static String str(Object o) {
        if (o == null) return null;
        if (o instanceof JsonNode node) {
            return node.isTextual() ? node.asText() : node.toString();
        }
        return String.valueOf(o);
    }

    private static int asInt(Object node, int def) {
        if (node == null) return def;
        if (node instanceof JsonNode n) {
            return n.isNumber() ? n.asInt(def) : def;
        }
        try { return Integer.parseInt(String.valueOf(node)); } catch (Exception ignored) { return def; }
    }
} 